程序中,在数据声明中定义的变量和数组,它们存储在静态存储区或者动态存储区,其空间由系统负责分配,最终也由系统负责回收,分配时机和回收时机用户无法控制。另外,它们都有自己的名字(因为定义时有命名),程序中可以通过变量名或数组名访问它们。
而“动态分配”的变量或数组,分配时机和释放时机可完全由程序员自己决定。另外,“动态分配”的空间,由于没有数据分明,因此这部分空间没有名字,无法像使用变量或数组那样通过变更名或数组名引用其中的数据,只能通过指针变量来访问。
对于数据在内存中的存储,C语言提供了3种策略,即静态分配、自动分配(栈式分配)和动态分配。
1 静态分配:静态分配由编译器自动分配和释放,在编译时就确定了运行时变量在内存中的位置。这种性质允许变量在整个程序的运行过程中都不消失。在C语言中使用关键字static来定义静态变量(可以是静态局部变量、静态全局变量或者在所有函数外面定义的全局变量)。
静态存储区是指存储单元在程序运行的整个过程中一直分配给某些变量,这些变量一直“静静地”占有这些单元,一直都不释放,直到程序运行结束。
2 自动内存分配(在栈上分配):自动分配同样也是由编译器自动分配和释放,在编译时并不确定变量在内存中的位置,而是在调用函数时给变量分配空间,函数返回时释放空间。C编译器通过系统栈来管理这样的变量。在C语言中,auto型变量是通过栈来管理的,不需要人为管理。
动态存储区是指存储单元在程序运行的不同时间可以分配不同的数据。需要时开辟单元,不需要时就释放该单元。这样某单元就可以在不同的时间分配给不同的变量,如函数里auto类型的局部变量就是这样,调用函数时,分配变量空间,退出函数时释放该空间。再调用时,再开辟...
3 动态内存分配(在堆上分配):动态分配是指在程序运行过程中动态申请内存的方法。这样的内存空间是从一个叫做堆的空间申请的,申请的空间是一段连续的内存空间。不需要该内存空间时,应该人为释放它,否则会导致内存资源的浪费。
内存中有一块称为“堆”(heap)的存储区,程序可以根据需要随时用stdlib.h提供的malloc()等函数在堆中申请一部分空间来存储数据,当不需要时又可以随时用free()函数释放。这种根据需要随时开辟、随时释放的内存分配方式,称为动态内存分配。
C语言中malloc()大体的实现是,从操作系统一次性地取得比较大的内存,然后将这些内存“零售”给应用程序。
堆区 动态内存分配 |
全局区 | 静态区 | 栈区 auto型变量 (内存重复使用) |
常量(只读) | |||
代码区(只读) |
(内存分配中的堆和栈与数据结构的堆和栈有本质的区别。)
C语言的变量有两种属性:数据类型和存储类型。存储类型标识符有:auto,extern,static,register。用来说明变量在计算机中不同的存储形态,包括存储位置、作用域和生存期。
要多少 | 具体在哪里 | 给谁用 | 何时给 | 用多久 |
数据类型 | 数据地址 | 作用域 | 内存分配 | 生存期 |
字节数量 | 作用的代码范围 | 从单元开辟到释放 |
函数调用时,主调函数的实参是准备好的具体数值,形参是函数调用时才开辟单元的变量。
在编写程序时,要告诉计算机这些数据的存储位置。变量的存储类型的功能之一就是确定该变量是存放在动态数据区、静态存放区还是寄存器中。
内存区 | 存储的内容 | ||
程序区 | 程序代码 | ||
数据区 | 静态存储区 | 全局变量、静态局部变量 | 编译阶段初始化,且只赋值一次,对静态局部变量多次调用时,每次在前一次的结果上进行。 |
动态存储区(栈区) | 局部动态变量、形参 | 在进入它们的函数或复合语句时才初始化,相当于赋值语句。每调用一次,就重新赋值一次。 | |
动态分配区 (栈区) |
动态数据 | 程序运行时与用户交互完成。 | |
(数据还可以存放在寄存器中) |
变量存储类型 | 作用域 | 生存期 | |
auto | 局部变量 | 所定义函数内部 | 所定义函数运行期间 |
全部变量 | 所定义之处到本源文件结束 | 程序运行的整个过程 | |
static | 局部变量 | 所定义函数内部 | 程序运行的整个过程 |
全部变量 | 所定义之处到本源文件结束,限于本文件 | 程序运行的整个过程 | |
register | 局部变量 | 所定义函数内部 | 所定义函数运行期间 |
extern | 全部变量 | 所定义之处到本源文件结束 | 程序运行的整个过程 |